<?php
/**
 * 自动加载模块下的Logic层所有类进行统一管理
 */
namespace app\common;
class AppLogic
{
    // 保存Logic类实例化后的对象
    protected $logicClasses = [];

    /**
     * 构造函数，自动加载Logic层类
     * @access public
     * @param string $module 指定模块
     * @return void
     */
    public function __construct($module = 'api')
    {

        $this->load('api');
    }


    /**
     * 加载应用下的Logic层所有类
     * @param string     $module     模块名
     * @return void
     */
    public function load(string $module)
    {
        // 验证模块是否存在
        if (!is_dir(app()->getBasePath() . $module)) {
            return;
        }
        // 获取模块的Logic类目录
        $logicPath = app()->getBasePath() . $module . '/logic/';
        // 遍历目录下的所有Logic类文件
        $files = scandir($logicPath);
        foreach ($files as $file) {
            if (is_file($logicPath . $file) && pathinfo($file, PATHINFO_EXTENSION) == 'php') {
                // 获取Logic类名 不区分大小写
                $logicName = strtolower(pathinfo($file, PATHINFO_FILENAME));

                // 引入Logic类文件

                include_once $logicPath . $file;
                // 将Logic类实例化并保存到类的属性中
                if (!isset($this->logicClasses[$logicName])) {
                  
                    $this->logicClasses[$logicName] = "\\app\\{$module}\\logic\\{$logicName}";
                }
            }
        }



 
    }

    /**
     * 魔术方法，动态设置Logic类的属性或方法
     * @access public
     * @param string     $name      Logic类名
     * @param mixed      $value     Logic类实例化后的对象
     * @return void
     */
    public function __set($name, $value)
    {
        $this->logicClasses[$name] = $value;
    }

    /**
     * 魔术方法，实现对Logic类的实例化
     * @param string     $name      Logic类名
     * @return mixed
     * @throws \Exception
     */
    public function __get(string $name)
    {
        // 不区分大小写
        $name = strtolower($name);

        if (array_key_exists($name, $this->logicClasses)) {
            if (is_string($this->logicClasses[$name])) {
                $this->logicClasses[$name] = app()->make($this->logicClasses[$name]);
            }

            return $this->logicClasses[$name];
        }

        throw new \Exception("Property {$name} not found.");
    }

    /**
     * 遍历执行配置中的模块，并返回执行结果
     * @param array     $page_module    配置中的模块
     * @param array     $args           页面传参
     * @return array
     */
    public function run(array $page_module, array $args = [])
    {	
        $result = [];

        // 遍历处理需要执行的模块
        $run_module = [];

        foreach ($page_module as $key => $value) {
            $only = false; // 是否仅加载当前模块
            list($class, $method) = explode('.', $value);

            // 判断是否有模块传参
            if (strpos($method, '?')) {
                $moduleArgs = [];
                parse_str(parse_url($method, PHP_URL_QUERY), $moduleArgs);

                // 判断模块传参中是否有只应用于指定方法的参数
                if (isset($moduleArgs['apply']) && !empty($moduleArgs['apply'])) {
                    // 判断当前页面传参中是否有指定应用的模块
                    $flag = is_array($moduleArgs['apply']) ? count(array_intersect($moduleArgs['apply'], $args)) <= 0 : !in_array($moduleArgs['apply'], $args);
                    if ($flag) {
                        continue; // 如果没有，则跳过该模块
                    }
                    unset($moduleArgs['apply']);
                    // 判断是否仅加载当前模块
                    if (isset($moduleArgs['load']) && $moduleArgs['load'] == 'alone') {
                        $only = true;
                        unset($moduleArgs['load']);
                    }
                }

                // 合并页面传参和模块传参
                $args = array_replace_recursive($args, $moduleArgs);
                // 去掉模块传参
                $method = explode('?', $method)[0];
            }

            if ($only) {
                $run_module = ['class' => $class, 'method' => $method, 'args' => $args];
                break;
            }else{
                $run_module[] = ['class' => $class, 'method' => $method, 'args' => $args];
            }
        }

        // 遍历运行模块
        $runTimes = [];
 
        foreach ($run_module as $k => $v) {
            $data = $this->{$v['class'] . 'Logic'}->{$v['method']}($v['args']);

            if(isset($data['back_type'])){
                  $result['code'] = $data['code'];
                  $result['msg'] = $data['msg']??'';
                  unset($data['code'],$data['msg'],$data['back_type']);
            }
            $result[strtolower($v['class'])."_".strtolower($v['method'])] = $data['data'] ?? $data;

            //$result[strtolower($v['method'])] = $data;
            
             
        }
        // 返回执行结果
        return $result;
    }

}
